/*********************************************************************************
 *      Copyright:  (C) 2025 YANG Studio
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(27/05/25)
 *         Author:  YANG JIAYU <yangjiayu@gmail.com>
 *      ChangeLog:  1, Release initial version on "27/05/25 18:53:41"
 *                 
 ********************************************************************************/
#include "stm32f1xx_hal.h"  // 包含STM32硬件抽象层库，自动引入设备相关头文件
#include "./SYSTEM/sys/sys.h"  // 系统功能头文件，包含时钟配置等
#include "./SYSTEM/usart/usart.h"  // 串口通信功能头文件
#include "./SYSTEM/delay/delay.h"  // 延时函数头文件
#include "./USMART/usmart.h"  // 智能串口调试组件头文件
#include "./BSP/LED/led.h"  // LED驱动头文件
#include "./BSP/LCD/lcd.h"  // LCD显示驱动头文件
#include "./BSP/LSENS/lsens.h"  // 光照传感器驱动头文件
#include "./BSP/DHT11/dht11.h"  // DHT11温湿度传感器驱动头文件
#include "./BSP/MQ2/mq2.h"  // MQ2气体传感器驱动头文件
#include "./BSP/FAN/fan.h"  // 风扇控制驱动头文件
#include "./BSP/BUZZER/buzzer.h"  // 蜂鸣器控制驱动头文件
#include "./BSP/ESP8266/esp8266.h"  // ESP8266 WiFi模块驱动头文件
#include <string.h>         // 引入C字符串处理库，用于字符串操作

// 系统配置宏定义
#define WIFI_SSID       "YourWiFiSSID"  // WiFi名称（需替换为实际网络名称）
#define WIFI_PASSWORD   "YourWiFiPassword"  // WiFi密码（需替换为实际密码）
#define SERVER_IP       "192.168.1.100"  // 服务器IP地址
#define SERVER_PORT     8080  // 服务器通信端口
#define MQ2_THRESHOLD   1000  // MQ2气体浓度报警阈值（超过此值触发报警）
#define TEMP_THRESHOLD  35    // 温度报警阈值（单位：摄氏度）
#define HUMI_THRESHOLD  80    // 湿度报警阈值（单位：%）


int main(void)
{
    short adcx;                 // 存储光照传感器采集的数值
    uint8_t t = 0;              // 循环计数器，用于控制数据采集频率
    uint8_t temperature;        // 存储温度值（单位：摄氏度）
    uint8_t humidity;           // 存储湿度值（单位：%）
    uint8_t dht11_status = 0;   // DHT11传感器初始化状态标志
    uint32_t mq2_value;         // 存储MQ2气体传感器采集的数值
    uint8_t esp8266_status = 0; // ESP8266模块状态标志
    uint8_t fan_status = 0;     // 风扇状态标志（0=关闭，1=开启）
    uint8_t mq2_alarm = 0;      // MQ2气体浓度报警标志
    uint8_t temp_alarm = 0;     // 温度报警标志
    uint8_t humi_alarm = 0;     // 湿度报警标志
    uint8_t system_alarm = 0;   // 系统综合报警标志（任意传感器报警时置1）

    // 系统初始化部分
    HAL_Init();                 // 初始化STM32 HAL库
    sys_stm32_clock_init(RCC_PLL_MUL9);  // 配置系统时钟（PLL倍频9倍，最终72MHz）
    delay_init(72);             // 初始化延时函数，传入系统时钟频率72MHz
    usart_init(115200);         // 初始化串口通信，设置波特率115200
    led_init();                 // 初始化LED指示灯
    lcd_init();                 // 初始化LCD显示屏
    lsens_init();               // 初始化光照传感器
    mq2_init();                 // 初始化MQ2气体传感器
    fan_init();                 // 初始化风扇控制
    buzzer_init();              // 初始化蜂鸣器控制
    dht11_status = dht11_init(); // 初始化DHT11温湿度传感器并获取初始化状态
    ESP8266_Init();             // 初始化ESP8266 WiFi模块
    esp8266_status = ESP8266_CheckStatus(); // 检查ESP8266模块初始化状态

    // WiFi和服务器连接流程
    if (esp8266_status) {
        printf("Connecting to WiFi...\r\n");  // 串口输出连接WiFi提示
        if (!ESP8266_ConnectWiFi(WIFI_SSID, WIFI_PASSWORD)) {  // 连接指定WiFi
            printf("WiFi connection failed!\r\n");  // WiFi连接失败提示
        } else {
            printf("WiFi connected!\r\n");  // WiFi连接成功提示
            printf("Connecting to server...\r\n");  // 串口输出连接服务器提示
            if (!ESP8266_ConnectServer("TCP", SERVER_IP, SERVER_PORT)) {  // 连接TCP服务器
                printf("Server connection failed!\r\n");  // 服务器连接失败提示
            } else {
                printf("Server connected!\r\n");  // 服务器连接成功提示
            }
        }
    }

    // LCD界面初始化显示
    lcd_show_string(30,  50, 200, 16, 16, "STM32 Environmental Monitoring System", RED);  // 显示系统标题
    lcd_show_string(30,  70, 200, 16, 16, "Light Sensor", RED);  // 显示传感器类型
    lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);  // 显示版权信息
    lcd_show_string(30, 110, 200, 16, 16, "Light: ", BLUE);  // 光照值标签
    lcd_show_string(30, 130, 200, 16, 16, "Temp: ", BLUE);  // 温度值标签
    lcd_show_string(30, 150, 200, 16, 16, "Humi: ", BLUE);  // 湿度值标签
    lcd_show_string(30, 170, 200, 16, 16, "MQ2 Value: ", BLUE);  // MQ2值标签
    lcd_show_string(30, 190, 200, 16, 16, "Fan Status: ", BLUE);  // 风扇状态标签
    lcd_show_string(30, 210, 200, 16, 16, "WiFi Status: ", BLUE);  // WiFi状态标签
    lcd_show_string(30, 230, 200, 16, 16, "MQ2 Alarm: ", BLUE);  // MQ2报警状态标签
    lcd_show_string(30, 250, 200, 16, 16, "Temp Alarm: ", BLUE);  // 温度报警状态标签
    lcd_show_string(30, 270, 200, 16, 16, "Humi Alarm: ", BLUE);  // 湿度报警状态标签
    lcd_show_string(30, 290, 200, 16, 16, "Buzzer: ", BLUE);  // 蜂鸣器状态标签

    // 显示初始状态信息
    lcd_show_string(30 + 10 * 8, 210, 200, 16, 16, 
                   esp8266_status ? "Connected" : "Disconnected",  // 根据WiFi状态显示连接信息
                   esp8266_status ? GREEN : RED);  // 连接状态用不同颜色显示
    lcd_show_string(30 + 10 * 8, 230, 200, 16, 16, "Normal", GREEN);  // MQ2初始状态
    lcd_show_string(30 + 10 * 8, 250, 200, 16, 16, "Normal", GREEN);  // 温度初始状态
    lcd_show_string(30 + 10 * 8, 270, 200, 16, 16, "Normal", GREEN);  // 湿度初始状态
    lcd_show_string(30 + 10 * 8, 290, 200, 16, 16, "Off", GREEN);  // 蜂鸣器初始状态

    // 系统主循环
    while (1)
    { 
        // 读取并显示光照传感器数据
        adcx = lsens_get_val();  // 读取光照传感器数值
        lcd_show_xnum(30 + 10 * 8, 110, adcx, 3, 16, 0, BLUE);  // 在LCD指定位置显示光照值
        
        // 周期性读取温湿度数据（每10个循环一次）
        if (!dht11_status && t % 10 == 0) {  // 传感器正常且计数到10
            if (dht11_read_data(&temperature, &humidity) == 0) {  // 读取温湿度数据成功
                lcd_show_num(30 + 60, 130, temperature, 2, 16, BLUE);  // 显示温度值
                lcd_show_num(30 + 60, 150, humidity, 2, 16, BLUE);  // 显示湿度值
                
                // 读取MQ2气体传感器数据
                mq2_value = mq2_get_val();  // 读取MQ2传感器数值
                
                // MQ2气体浓度报警判断
                if (mq2_value > MQ2_THRESHOLD) {  // 超过报警阈值
                    mq2_alarm = 1;  // 置位报警标志
                    lcd_show_string(30 + 10 * 8, 230, 200, 16, 16, "ALARM!", RED);  // 显示报警状态
                } else {
                    mq2_alarm = 0;  // 清除报警标志
                    lcd_show_string(30 + 10 * 8, 230, 200, 16, 16, "Normal", GREEN);  // 显示正常状态
                }
                
                // 温度报警判断
                if (temperature > TEMP_THRESHOLD) {  // 超过温度阈值
                    temp_alarm = 1;  // 置位报警标志
                    lcd_show_string(30 + 10 * 8, 250, 200, 16, 16, "ALARM!", RED);  // 显示报警状态
                } else {
                    temp_alarm = 0;  // 清除报警标志
                    lcd_show_string(30 + 10 * 8, 250, 200, 16, 16, "Normal", GREEN);  // 显示正常状态
                }
                
                // 湿度报警判断
                if (humidity > HUMI_THRESHOLD) {  // 超过湿度阈值
                    humi_alarm = 1;  // 置位报警标志
                    lcd_show_string(30 + 10 * 8, 270, 200, 16, 16, "ALARM!", RED);  // 显示报警状态
                } else {
                    humi_alarm = 0;  // 清除报警标志
                    lcd_show_string(30 + 10 * 8, 270, 200, 16, 16, "Normal", GREEN);  // 显示正常状态
                }
                
                // 综合报警状态计算（只要一个传感器报警，系统即报警）
                system_alarm = mq2_alarm || temp_alarm || humi_alarm;
                
                // 蜂鸣器控制（根据综合报警状态）
                if (system_alarm) {
                    buzzer_on();  // 开启蜂鸣器
                    lcd_show_string(30 + 10 * 8, 290, 200, 16, 16, "On", RED);  // 显示蜂鸣器状态
                } else {
                    buzzer_off();  // 关闭蜂鸣器
                    lcd_show_string(30 + 10 * 8, 290, 200, 16, 16, "Off", GREEN);  // 显示蜂鸣器状态
                }
                
                // 风扇控制逻辑（温度≥40℃或MQ2报警时开启）
                if (temperature >= 40 || mq2_alarm) {
                    fan_on();  // 开启风扇
                    fan_status = 1;  // 记录风扇状态
                } else {
                    fan_off();  // 关闭风扇
                    fan_status = 0;  // 记录风扇状态
                }
                
                // 显示风扇状态
                lcd_show_string(30 + 10 * 8, 190, 200, 16, 16, 
                               fan_status ? "On" : "Off",  // 根据状态显示开关
                               fan_status ? GREEN : RED);  // 状态用不同颜色显示
                
                // 周期性向服务器发送数据（每20个循环一次）
                if (esp8266_status && t % 20 == 0) {  // WiFi正常且计数到20
                    char send_buf[100];  // 定义数据发送缓冲区
                    // 格式化数据字符串（包含温湿度、MQ2值、风扇状态、报警状态）
                    sprintf(send_buf, "T=%d,H=%d,MQ=%lu,FAN=%d,ALARM=%d,T_ALARM=%d,H_ALARM=%d", 
                            temperature, humidity, mq2_value, fan_status, mq2_alarm, temp_alarm, humi_alarm);
                    if (ESP8266_SendData((uint8_t*)send_buf, strlen(send_buf))) {  // 发送数据到服务器
                        printf("Data sent successfully: %s\r\n", send_buf);  // 发送成功提示
                    } else {
                        printf("Failed to send data!\r\n");  // 发送失败提示
                    }
                }
            }
        }

        // 独立读取并显示MQ2传感器数据（提高更新频率）
        mq2_value = mq2_get_val();  // 读取MQ2传感器数值
        lcd_show_xnum(30 + 10 * 8, 170, mq2_value, 4, 16, 0, BLUE);  // 显示MQ2数值
        
        // WiFi连接状态检查（每5个循环一次）
        if (t % 5 == 0 && esp8266_status) {  // 计数到5且WiFi已初始化
            if (!ESP8266_CheckStatus()) {  // 检查到服务器连接断开
                printf("Connection lost, trying to reconnect...\r\n");  // 输出重连提示
                // 更新LCD显示重连状态
                lcd_show_string(30 + 10 * 8, 210, 200, 16, 16, "Reconnecting", YELLOW);
                // 尝试重新连接WiFi和服务器
                if (!ESP8266_ConnectWiFi(WIFI_SSID, WIFI_PASSWORD)) {  // 重连WiFi
                    printf("WiFi reconnection failed!\r\n");  // WiFi重连失败
                } else {
                    printf("WiFi reconnected!\r\n");  // WiFi重连成功
                    if (!ESP8266_ConnectServer("TCP", SERVER_IP, SERVER_PORT)) {  // 重连服务器
                        printf("Server reconnection failed!\r\n");  // 服务器重连失败
                    } else {
                        printf("Server reconnected!\r\n");  // 服务器重连成功
                    }
                }
            } else {
                // 连接正常时更新LCD状态
                lcd_show_string(30 + 10 * 8, 210, 200, 16, 16, "Connected", GREEN);
            }
        }

        // 系统状态指示（LED闪烁作为心跳）
        LED0_TOGGLE();  // 翻转LED状态（亮灭切换）
        HAL_Delay(100);  // 延时100ms
        t++;  // 循环计数器自增
        if (t >= 20) t = 0;  // 计数器达到20时重置为0（形成0-19循环）
    }
}

